home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / Clipper.C < prev    next >
C/C++ Source or Header  |  1992-07-21  |  12KB  |  617 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "Clipper.h"
  6.  
  7. #include "Class.h"
  8. #include "Math.h"
  9. #include "View.h"
  10. #include "Error.h"
  11. #include "Token.h"
  12. #include "Window.h"
  13. #include "String.h"
  14. #include "WindowPort.h"
  15. #include "Collection.h"
  16.  
  17. //---- Clipper -----------------------------------------------------------------
  18.  
  19. NewMetaImpl(Clipper,VObject, (TP(vop), TB(deleteVop), T(minExtent),
  20.                     T(relOrigin), T(scale), TP(bgcolor))); 
  21.  
  22. Clipper::Clipper(VObject *vp, Point minsize, int id, Ink *bg)
  23.                             : VObject(minsize, id)
  24. {
  25.     if (bg == 0)
  26.     bg= gInkWhite;
  27.     bgcolor= bg;
  28.     vop= 0;
  29.     relOrigin= gPoint0;
  30.     scale= 1.0;
  31.     SetMinExtent(minsize);
  32.     ResetFlag(eVObjOpen);
  33.     deleteVop= FALSE;
  34.     Add(vp);
  35. }
  36.  
  37. Clipper::~Clipper()
  38. {
  39.     if (vop) {
  40.     VObject *tmp= vop;
  41.     vop= 0;
  42.     tmp->ClearContainer(this);
  43.     if (deleteVop)
  44.         delete tmp;
  45.     }
  46. }
  47.  
  48. void Clipper::Open(bool mode)
  49. {
  50.     if (IsOpen() != mode) {
  51.     VObject::Open(mode);
  52.     if (vop)
  53.         vop->Open(mode);
  54.     }
  55. }
  56.  
  57. void Clipper::Add(VObject *vp)
  58. {
  59.     Remove(vop);
  60.     vop= vp;
  61.     if (vop) {
  62.     vop->SetContainer(this);
  63.     if (IsOpen() && !vop->IsOpen())
  64.         vop->Open(TRUE);
  65.     ViewSizeChanged();
  66.     }
  67. }
  68.  
  69. VObject *Clipper::Remove(VObject *vp)
  70. {
  71.     if (vop && vop == vp) {
  72.     vop= 0;
  73.     if (vp->IsOpen())
  74.         vp->Open(FALSE);
  75.     vp->ClearContainer(this);
  76.     return vp;
  77.     }
  78.     return 0;
  79. }
  80.  
  81. void Clipper::SetContainer(VObject *v)
  82. {
  83.     VObject::SetContainer(v);
  84.     if (vop && !vop->IsKindOf(View)) {
  85.     vop->CalcExtent();
  86.     vop->SetOrigin(gPoint0);
  87.     }
  88. }
  89.  
  90. void Clipper::Enable(bool b, bool redraw)
  91. {
  92.     VObject::Enable(b, redraw);
  93.     if (vop)
  94.     vop->Enable(b, redraw);
  95. }
  96.  
  97. void Clipper::ScaleUp(Point &p)
  98. {
  99.     p.x= (int) ((float)p.x * scale + 0.5);
  100.     p.y= (int) ((float)p.y * scale + 0.5);
  101. }
  102.  
  103. void Clipper::ScaleDown(Point &p)
  104. {
  105.     p.x= (int) ((float)p.x / scale + 0.5);
  106.     p.y= (int) ((float)p.y / scale + 0.5);
  107. }
  108.  
  109. Point Clipper::GetViewSize()
  110. {
  111.     Point p;
  112.     if (vop)
  113.     p= vop->GetExtent();
  114.     ScaleUp(p);
  115.     return p;
  116. }
  117.  
  118. Rectangle Clipper::GetViewedRect()
  119. {
  120.     return Rectangle(relOrigin, contentRect.extent);
  121. }
  122.  
  123. void Clipper::SetZoom(float zoom)
  124. {
  125.     scale= zoom;
  126.     ViewSizeChanged();
  127.     ForceRedraw();
  128. }
  129.  
  130. Metric Clipper::GetMinSize()
  131. {
  132.     Point me(minExtent);
  133.     if (vop && (minExtent.x == -1 || minExtent.y == -1)) {
  134.     Point e= vop->GetMinSize().extent;
  135.     if (minExtent.x == -1)
  136.         me.x= e.x;
  137.     if (minExtent.y == -1)
  138.         me.y= e.y;
  139.     }
  140.     //if (vop)
  141.     //    return Metric(me, vop->Base());
  142.     return me;
  143. }
  144.  
  145. void Clipper::SetMinExtent(Point e)
  146. {
  147.     minExtent= e;
  148.     if (e.x == -1)
  149.     SetFlag(eVObjHFixed);
  150.     if (e.y == -1)
  151.     SetFlag(eVObjVFixed);
  152. }
  153.  
  154. void Clipper::ViewSizeChanged()
  155. {
  156.     if (vop) {
  157.     Point newsize(vop->GetExtent());
  158.     ScaleUp(newsize);
  159.     Send(GetId(), cPartViewSize, &newsize);
  160.     Normalize();
  161.     }
  162. }
  163.  
  164. void Clipper::InvalidateViewRect(Rectangle r)
  165. {
  166.     r.origin= ContainerPoint(r.origin);
  167.     ScaleUp(r.extent);
  168.     InvalidateRect(r);
  169. }
  170.  
  171. void Clipper::SetExtent(Point e)
  172. {
  173.     VObject::SetExtent(e);
  174.     Normalize();
  175. }
  176.  
  177. void Clipper::SetOrigin(Point at)
  178. {
  179.     VObject::SetOrigin(at);
  180.     if (vop)
  181.     vop->SetOrigin(gPoint0);
  182. }
  183.  
  184. void Clipper::Normalize()
  185. {
  186.     Point vs(GetViewSize()), ee(GetExtent()), scroll;
  187.  
  188.     if (vs.x < ee.x)
  189.     scroll.x= -relOrigin.x;
  190.     else if (vs.x < relOrigin.x+ee.x)
  191.     scroll.x= relOrigin.x+ee.x - vs.x;
  192.  
  193.     if (vs.y < ee.y)
  194.     scroll.y= -relOrigin.y;
  195.     else if (vs.y < relOrigin.y+ee.y)
  196.     scroll.y= relOrigin.y+ee.y - vs.y;
  197.  
  198.     Scroll(cPartScrollRel, scroll);
  199. }
  200.  
  201. void Clipper::Focus()
  202. {
  203.     if (GetContainer()) {
  204.     GetContainer()->Focus();
  205.     GrClipFurther(contentRect);
  206.     GrTranslate(Offset());
  207.     GrScale(scale, scale);
  208.     }
  209. }
  210.  
  211. void Clipper::DrawInner(Rectangle r, bool)
  212. {
  213.     if (bgcolor && bgcolor != ePatNone && !gPrinting)
  214.     GrPaintRect(r, bgcolor);
  215.     
  216.     if (vop) {
  217.     GrState gs;
  218.     GrClipFurther(r);
  219.     GrTranslate(Offset());
  220.     GrScale(scale, scale);
  221.  
  222.     r.origin-= Offset();
  223.     ScaleDown(r.origin);
  224.     ScaleDown(r.extent);
  225.  
  226.     vop->DrawAll(r, FALSE);
  227.     }
  228. }
  229.  
  230. VObject *Clipper::Detect(BoolFun find, void *arg)
  231. {
  232.     VObject *v;
  233.     if (vop && (v= vop->Detect(find, arg)))
  234.     return v;
  235.     return VObject::Detect(find, arg);
  236. }
  237.  
  238. void Clipper::ReadEvent(Token &t, int timeout, bool overread)
  239. {
  240.     VObject::ReadEvent(t, timeout, overread);
  241.     t.Pos-= Offset();
  242.     ScaleDown(t.Pos);
  243. }
  244.  
  245. Command *Clipper::DispatchEvents(Point lp, Token &t, Clipper *vf)
  246. {
  247.     Command *cmd= 0;
  248.     
  249.     lp-= Offset();
  250.     ScaleDown(lp);
  251.  
  252.     if (vop)
  253.     cmd= vop->Input(lp, t, this);
  254.     else
  255.     cmd= VObject::DispatchEvents(lp, t, vf);
  256.     if (cmd)
  257.     PerformCommand(cmd);
  258.     return gNoChanges;
  259. }
  260.  
  261. Point Clipper::ContainerPoint(Point p)
  262. {
  263.     ScaleUp(p);
  264.     return p+Offset();
  265. }
  266.  
  267. void Clipper::SetBgInk(Ink *ip)
  268. {
  269.     bgcolor= ip;
  270.     ForceRedraw();
  271. }
  272.  
  273. Ink *Clipper::GetBgInk()
  274. {
  275.     return bgcolor;
  276. }
  277.  
  278. //---- Scrolling ----------------------------------------------------------------
  279.  
  280. Point Clipper::AutoScroll(Point p)
  281. {
  282.     ScaleUp(p);
  283.     p-= relOrigin;
  284.     Point scroll= Rectangle(contentRect.extent).Constrain(p);
  285.     Scroll(cPartScrollRel, scroll-p);
  286.     return scroll;
  287. }
  288.  
  289. void Clipper::RevealRect(Rectangle r, Point minToSee)
  290. {
  291.     ScaleUp(r.extent);
  292.     ScaleUp(minToSee);
  293.     VObject::RevealRect(Rectangle(ContainerPoint(r.origin), r.extent), minToSee);
  294.     ScaleUp(r.origin);
  295.  
  296.     Rectangle vr(relOrigin, contentRect.extent);
  297.     Rectangle ir(Inter(r, vr));
  298.     
  299.     if (ir.IsEmpty() || ir.extent.x < minToSee.x || ir.extent.y < minToSee.y)
  300.     Scroll(cPartScrollRel, r.AmountToTranslateWithin(vr));
  301. }
  302.  
  303. void Clipper::RevealAlign(Rectangle r, VObjAlign al)
  304. {
  305.     ScaleUp(r.origin);
  306.     ScaleUp(r.extent);
  307.  
  308.     Rectangle vr= GetViewedRect();
  309.     Point scroll;
  310.  
  311.     switch (al & eVObjH) {
  312.     case eVObjHCenter:
  313.     scroll.x= (vr.Center().x - r.Center().x)/2;
  314.     break;
  315.     case eVObjHRight:
  316.     scroll.x= vr.NE().x - r.NE().x;
  317.     break;
  318.     default:
  319.     scroll.x= vr.NW().x - r.NW().x;
  320.     break;
  321.     }
  322.     switch (al & eVObjV) {
  323.     case eVObjVCenter:
  324.     scroll.y= (vr.Center().y - r.Center().y)/2;
  325.     break;
  326.     case eVObjVBottom:
  327.     scroll.y= vr.SW().y - r.SW().y;
  328.     break;
  329.     default:
  330.     scroll.y= vr.NW().y - r.NW().y;
  331.     break;
  332.     }
  333.     Scroll(cPartScrollRel, scroll);
  334. }
  335.  
  336. void Clipper::ExtentChanged(VObject*)
  337. {
  338.     ViewSizeChanged();
  339. }
  340.  
  341. void Clipper::Control(int id, int part, void *val)
  342. {
  343.     if (part == cPartExtentChanged) {
  344.     if (val == vop)
  345.         ViewSizeChanged();
  346.     }
  347.     VObject::Control(id, part, val);
  348. }
  349.  
  350. void Clipper::SendDown(int id, int part, void *val)
  351. {
  352.     if (vop)
  353.     vop->SendDown(id, part, val);
  354. }
  355.  
  356. void Clipper::Scroll(int mode, Point scroll, bool redraw)
  357. {
  358.     Point leftCorner, newOrigin, delta;
  359.     
  360.     if (GetContainer() == 0)
  361.     return;
  362.     
  363.     switch(mode) {
  364.     case cPartScrollStep:
  365.     delta= 32 * -scroll;
  366.     break;
  367.     case cPartScrollPage:
  368.     delta= (contentRect.extent-32) * -scroll;
  369.     break;
  370.     case cPartScrollAbs:
  371.     delta= relOrigin - scroll;
  372.     break;
  373.     case cPartScrollHAbs:
  374.     delta.x= relOrigin.x - scroll.x;
  375.     break;
  376.     case cPartScrollVAbs:
  377.     delta.y= relOrigin.y - scroll.y;
  378.     break;
  379.     case cPartScrollRel:
  380.     delta= scroll;
  381.     break;
  382.     }
  383.     
  384.     if (delta == gPoint0)
  385.     return;
  386.     
  387.     leftCorner= Max(gPoint0, GetViewSize() - contentRect.extent);
  388.     newOrigin= relOrigin-delta;
  389.     
  390.     if (vop && vop->IsKindOf(View))
  391.     ((View*)vop)->ConstrainScroll(&newOrigin);
  392.     
  393.     delta= relOrigin - Min(Max(gPoint0, newOrigin), leftCorner);
  394.     
  395.     if (delta == gPoint0)
  396.     return;
  397.     
  398.     if (! IsOpen())
  399.     redraw= FALSE;
  400.     
  401.     if (redraw) {
  402.     UpdateEvent();
  403.     Focus();
  404.     relOrigin-= delta;
  405.     ((WindowPort*)GrGetPort())->Scroll(delta);
  406.     } else
  407.     relOrigin-= delta;
  408.     Send(GetId(), cPartScrollPos, &relOrigin);
  409.     UpdateEvent();
  410. }
  411.  
  412. // returns TRUE on exit loop
  413. bool Clipper::TrackOnce(Command** tracker, TrackPhase atp, Point ap, Point pp, Point lp)
  414. {
  415.     Command *newTracker;
  416.  
  417.     if (*tracker == 0) {
  418.     *tracker= gNoChanges;
  419.     return TRUE;
  420.     }
  421.  
  422.     newTracker= (*tracker)->TrackMouse(atp, ap, pp, lp);
  423.     if (newTracker != *tracker) {
  424.     if (*tracker && *tracker != gNoChanges)
  425.         delete *tracker;
  426.     *tracker= newTracker;
  427.     return (newTracker == gNoChanges);
  428.     }
  429.     return FALSE;
  430. }
  431.  
  432. // called from View
  433. void Clipper::DrawInFocus(VoidObjMemberFunc of, Object *op, void *v1, void *v2, void *v3, void *v4)
  434. {
  435.     if (IsOpen()) {
  436.     Focus();
  437.     (op->*of)(v1, v2, v3, v4);
  438.     }
  439. }
  440.  
  441. void Clipper::Feedback(Object *tracker, void *ap, void *pp, void *turniton)
  442. {
  443.     GrPattern pat= ePatBlack;
  444.     if (((Command*)tracker)->TestFlag(eCmdFullScreen) ||
  445.             ! ((Command*)tracker)->TestFlag(eCmdNoReplFeedback))
  446.     pat= ePatXor;
  447.     GrSetInk(pat);
  448.     GrSetPenInk(pat);
  449.     GrSetTextInk(pat);
  450.     GrSetPenSize(1);
  451.     ((Command*)tracker)->TrackFeedback(*((Point*)ap), *((Point*)pp), *((bool*)turniton));
  452.     UpdateEvent();
  453. }
  454.  
  455. void Clipper::FeedbackOnce(Command *tracker, Point ap, Point pp, bool turniton)
  456. {            
  457.     if (!tracker->TestFlag(eCmdNoReplFeedback) && vop && vop->IsKindOf(View))
  458.     ((View*)vop)->ShowInAllClippers((VoidObjMemberFunc)&Clipper::Feedback, this,
  459.         (void*) tracker, (void*) &ap, (void*) &pp, (void*) &turniton);
  460.     else
  461.     Feedback(tracker, (void*) &ap, (void*) &pp, (void*) &turniton);
  462. }
  463.  
  464. Command *Clipper::TrackInContent(Point lp, Token token, Command* tracker)
  465. {
  466.     static int level= 0;
  467.     static bool haveSeenUp;
  468.     
  469.     bool autoscroll= FALSE, havereset, isidle= FALSE, fullscreen, done;
  470.     Point newlp, ap, pp, oldrelorigin;
  471.     Window *bwin= GetWindow();
  472.       
  473.     level++;
  474.     if (level == 1)
  475.     haveSeenUp= FALSE;
  476.     Focus();
  477.     
  478.     bwin->Grab(TRUE, fullscreen= tracker->TestFlag(eCmdFullScreen));
  479.     havereset= FALSE;
  480.  
  481. restart2:
  482.     ap= pp= lp;
  483.     tracker->TrackConstrain(ap, pp, &lp);
  484.     ap= pp= lp;
  485.  
  486.     if (TrackOnce(&tracker, eTrackPress, ap, pp, lp))
  487.     goto out;
  488.     FeedbackOnce(tracker, ap, pp, TRUE);
  489.  
  490. restart:
  491.     while (IsOpen()) {
  492.     if (level > 0 && haveSeenUp && !tracker->TestFlag(eCmdMoveEvents))
  493.         break;
  494.         
  495.     done= FALSE;
  496.     while (!done) {
  497.         if (isidle || autoscroll)
  498.         ReadEvent(token, 0, TRUE);
  499.         else
  500.         ReadEvent(token, 100, FALSE);
  501.         
  502.         switch (token.Code) {
  503.         
  504.         case eEvtNone:
  505.         if (autoscroll) {
  506.             token.Code= eEvtLocMove;   // simulate a move event
  507.             done= TRUE;
  508.             break;
  509.         }
  510.         if (tracker->TestFlag(eCmdIdleEvents)) {
  511.             done= isidle= TRUE;
  512.             break;
  513.         }
  514.         //done= haveSeenUp= TRUE;
  515.         break;
  516.         
  517.         case eEvtRightButton:
  518.         case eEvtMiddleButton:
  519.         case eEvtLeftButton:
  520.         if (token.Flags & eFlgButDown)
  521.             haveSeenUp= TRUE;
  522.         else
  523.             goto restart2;
  524.         done= TRUE;                     // return button event immediately
  525.         break;
  526.         
  527.         case eEvtLocMove:
  528.         done= TRUE;
  529.         break;
  530.         
  531.         case eEvtIdle:                      // ignore idle events
  532.         break;
  533.         
  534.         default:
  535.         break;
  536.         }
  537.     }
  538.  
  539.     lp= token.Pos;
  540.     
  541.     if (haveSeenUp)
  542.         break;
  543.           
  544.     FeedbackOnce(tracker, ap, pp, FALSE);   // clear previous feedback
  545.     
  546.     tracker->TrackConstrain(ap, pp, &lp);
  547.     if (! fullscreen) {
  548.         oldrelorigin= relOrigin;
  549.         newlp= AutoScroll(lp);
  550.         if (relOrigin != oldrelorigin) {
  551.         autoscroll= TRUE;
  552.         lp= newlp + relOrigin;
  553.         } else
  554.         autoscroll= FALSE;
  555.     }
  556.     oldrelorigin= relOrigin;
  557.     if (TrackOnce(&tracker,
  558.         token.Code == eEvtLocMove ? eTrackMove : eTrackIdle, ap, pp, lp))
  559.         goto out;
  560.     
  561.     pp= lp;
  562.     FeedbackOnce(tracker, ap, pp, TRUE);    // new feedback
  563.     }
  564.     FeedbackOnce(tracker, ap, pp, FALSE);   // clear last feedback
  565.     tracker->TrackConstrain(ap, pp, &lp);
  566.     
  567.     if (! tracker->TestFlag(eCmdMoveEvents)) {
  568.     bwin->Grab(FALSE, fullscreen);
  569.     havereset= TRUE;
  570.     level--;
  571.     }
  572.         
  573.     TrackOnce(&tracker, IsOpen() ? eTrackRelease : eTrackExit, ap, pp, lp);
  574.  
  575.     if (tracker->TestFlag(eCmdMoveEvents)) {
  576.     haveSeenUp= FALSE;
  577.     goto restart;
  578.     }
  579. out:
  580.     Focus();
  581.     if (! havereset) {
  582.     bwin->Grab(FALSE, fullscreen);
  583.     level--;
  584.     }
  585.     return tracker;
  586. }
  587.  
  588. OStream& Clipper::PrintOn(OStream &s)
  589. {
  590.     VObject::PrintOn(s);
  591.     return s << minExtent SP << scale SP << vop SP << bgcolor SP;
  592. }
  593.  
  594. IStream& Clipper::ReadFrom(IStream &s)
  595. {
  596.     VObject::ReadFrom(s);
  597.     s >> minExtent >> scale >> vop >> bgcolor;
  598.     Add(vop);
  599.     SetContentRect(contentRect, TRUE);
  600.     return s;
  601. }
  602.  
  603. void Clipper::InspectorId(char *buf, int sz)
  604. {
  605.     if (vop) 
  606.     vop->InspectorId(buf, sz);
  607.     else
  608.     VObject::InspectorId(buf, sz);   
  609. }
  610.  
  611. void Clipper::CollectParts(Collection* col)
  612. {
  613.     VObject::CollectParts(col);
  614.     if (vop)
  615.     col->Add(vop);
  616. }
  617.